

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% INIT

% parameters
NCOMP = 1; % number of mixture components
USE_WEEKEND = 0; % including weekend tag in models
PRINT_ALL = 1; % print all cluster divergence scores

% path
oldPath = path;
addpath(genpath('../../data/ours/'));

% meta-feature labels
fid = fopen('mflabels.txt');
C = textscan(fid, '%d %s');
fclose(fid);
metafeatureIDs = C{1};
metafeatureLABELs = C{2};
clear C;
numMetafeatures = length(metafeatureIDs);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  TRAIN  %
%                                                                         %
%  A meta-feature classifier is built by computing a MoG for each sensor  %
%  and grouping these models by meta-feature. These clusters represent    %
%  our model for each meta-feature.                                       %
%                                                                         %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

load firings_A_sec.txt;
if ~USE_WEEKEND,
  firings_A_sec = firings_A_sec(:,1:3);
end
load mfmap_A.txt;
sensorIDs_A = mfmap_A(:,1);
numSensors_A = length(sensorIDs_A);

allmog_A = cell(numSensors_A,1);
mf_clusters_A = cell(numMetafeatures,1);

fprintf('Computing mixture models for sensors of house A.\n');

for idx=1:numSensors_A,
  X = firings_A_sec(firings_A_sec(:,1)==sensorIDs_A(idx),2:end);
  allmog_A{idx} = gm_process_sensor(X, 'Blue', 0, NCOMP);
end

fprintf('Computing meta-feature clusters for house A.\n');

for idx=1:numMetafeatures,
  mog_ids = mfmap_A(:,2)==metafeatureIDs(idx);
  fprintf('Meta-feature %2d (%s): %d sensors.\n', ...
      metafeatureIDs(idx),metafeatureLABELs{idx},sum(mog_ids));
  if sum(mog_ids) == 0,
    % no sensors corresponding to this meta-feature
    mf_clusters_A{idx} = cell(0);
  else
    mf_clusters_A{idx} = allmog_A(mog_ids);
  end
end


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  TEST  %
%                                                                         %
%  Find for each 'anonymous' cluster (meta-feature of house B) the        %
%  best 'candidate' match (meta-feature of house A).                      %
%                                                                         %
%  The mapping is a function but has no inverse: multiple anonymous       %
%  clusters can be matched to the same candidate cluster.                 %
%                                                                         %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

load firings_B_sec.txt;
if ~USE_WEEKEND,
  firings_B_sec = firings_B_sec(:,1:3);
end
load mfmap_B.txt;
sensorIDs_B = mfmap_B(:,1);
numSensors_B = length(sensorIDs_B);

fprintf('\nComputing mixture models for sensors of house B.\n');

allmog_B = cell(numSensors_B,1);
for idx=1:numSensors_B,
  X = firings_B_sec(firings_B_sec(:,1)==sensorIDs_B(idx),2:end);
  allmog_B{idx} = gm_process_sensor(X, 'Blue', 0, NCOMP);
end

fprintf('Computing meta-feature clusters for house B.\n');

mf_clusters_B = cell(numMetafeatures,1);
for idx=1:numMetafeatures,
  mog_ids = mfmap_B(:,2)==metafeatureIDs(idx);
  fprintf('Meta-feature %2d (%s): %d sensors.\n', ...
      metafeatureIDs(idx),metafeatureLABELs{idx},sum(mog_ids));
  if sum(mog_ids) == 0,
    % no sensors corresponding to this meta-feature
    mf_clusters_B{idx} = cell(0);
  else
    mf_clusters_B{idx} = allmog_B(mog_ids);
  end
end

fprintf('\nFinding best matches for houseB->houseA (normal).\n');

% for each 'anonymous' cluster in houseB
for idxAnonymous=1:length(mf_clusters_B),
    
  anonymous = mf_clusters_B{idxAnonymous};
  
  if isempty(anonymous),
    continue;
  end
  
  fprintf('Compute divergence scores for %s/B.\n', ...
    metafeatureLABELs{idxAnonymous});
  
  minDiv = inf;
  ordCandidate = inf;

  % find best matching 'candidate' cluster from houseA
  for idxCandidate=1:numMetafeatures,
    candidate = mf_clusters_A{idxCandidate};
    curDiv = compute_cluster_divergence(anonymous, candidate);
    
    if PRINT_ALL && curDiv ~= inf,
      fprintf('  -> %s/A (%f)\n', ...
        metafeatureLABELs{idxCandidate}, ...
        curDiv);
    end
    
    if curDiv < minDiv,
      minDiv = curDiv;
      ordCandidate = idxCandidate;
    end
  end
  
  if isinf(ordCandidate),
    continue;
  else    
    fprintf('Best match for %s/B: %s/A (%f)\n', ...
      metafeatureLABELs{idxAnonymous}, ...
      metafeatureLABELs{ordCandidate}, ...
      minDiv);
  end
  
end

% restore old MATLAB path
path(oldPath);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  RESULTS  %
%                                                                         %
%   Computing mixture models for sensors of house A.
%   Computing meta-feature clusters for house A.
%   Meta-feature  1 (KitchHeat): 1 sensors.
%   Meta-feature  2 (Toilet): 2 sensors.
%   Meta-feature  3 (BathroomDoor): 1 sensors.
%   Meta-feature  4 (Kitchen): 6 sensors.
%   Meta-feature  5 (KitchStor): 2 sensors.
%   Meta-feature  6 (Outside): 1 sensors.
%   Meta-feature  7 (SleepDoor): 1 sensors.
%   Meta-feature  8 (Sleep): 0 sensors.
%   Meta-feature  9 (Bathroom): 0 sensors.
%   Meta-feature 10 (Other): 0 sensors.
% 
%   Computing mixture models for sensors of house B.
%   Computing meta-feature clusters for house B.
%   Meta-feature  1 (KitchHeat): 3 sensors.
%   Meta-feature  2 (Toilet): 1 sensors.
%   Meta-feature  3 (BathroomDoor): 1 sensors.
%   Meta-feature  4 (Kitchen): 3 sensors.
%   Meta-feature  5 (KitchStor): 2 sensors.
%   Meta-feature  6 (Outside): 1 sensors.
%   Meta-feature  7 (SleepDoor): 1 sensors.
%   Meta-feature  8 (Sleep): 4 sensors.
%   Meta-feature  9 (Bathroom): 2 sensors.
%   Meta-feature 10 (Other): 0 sensors.
% 
%   Finding best matches for houseB->houseA (normal).
%
%   Compute divergence scores for KitchHeat/B.
%     -> KitchHeat/A (0.955034)
%     -> Toilet/A (1.876557)
%     -> SleepDoor/A (2.646767)
%     -> BathroomDoor/A (4.528986)
%     -> KitchStor/A (7.284945)
%     -> Outside/A (10.341494)
%     -> Kitchen/A (98.354595)
%   Best match for KitchHeat/B: KitchHeat/A (0.955034)
%
%   Compute divergence scores for Toilet/B.
%     -> BathroomDoor/A (0.289841)
%     -> KitchStor/A (0.373872)
%     -> Toilet/A (0.847914)
%     -> Outside/A (6.403052)
%     -> Kitchen/A (7.006550)
%     -> SleepDoor/A (16.996380)
%     -> KitchHeat/A (112.069744)
%   Best match for Toilet/B: BathroomDoor/A (0.289841)
%
%   Compute divergence scores for BathroomDoor/B.
%     -> Toilet/A (0.214715)
%     -> BathroomDoor/A (0.795793)
%     -> SleepDoor/A (2.467421)
%     -> KitchStor/A (2.513195)
%     -> Kitchen/A (4.720513)
%     -> Outside/A (6.987380)
%     -> KitchHeat/A (44.520090)
%   Best match for BathroomDoor/B: Toilet/A (0.214715)
%
%   Compute divergence scores for Kitchen/B.
%     -> Outside/A (0.490499)
%     -> Kitchen/A (1.055787)
%     -> KitchStor/A (23.145716)
%     -> BathroomDoor/A (38.610469)
%     -> Toilet/A (82.488592)
%     -> SleepDoor/A (177.289697)
%     -> KitchHeat/A (199.189827)
%   Best match for Kitchen/B: Outside/A (0.490499)
%
%   Compute divergence scores for KitchStor/B.
%     -> BathroomDoor/A (0.728077)
%     -> KitchHeat/A (2.353579)
%     -> KitchStor/A (3.652581)
%     -> SleepDoor/A (6.185445)
%     -> Outside/A (6.601085)
%     -> Toilet/A (8.698513)
%     -> Kitchen/A (80.379661)
%   Best match for KitchStor/B: BathroomDoor/A (0.728077)
%
%   Compute divergence scores for Outside/B.
%     -> Outside/A (0.326673)
%     -> Kitchen/A (0.882407)
%     -> KitchStor/A (1.262743)
%     -> Toilet/A (6.860550)
%     -> BathroomDoor/A (202.254947)
%     -> KitchHeat/A (207.241585)
%     -> SleepDoor/A (207.966321)
%   Best match for Outside/B: Outside/A (0.326673)
%
%   Compute divergence scores for SleepDoor/B.
%     -> KitchHeat/A (0.289469)
%     -> SleepDoor/A (0.907968)
%     -> BathroomDoor/A (3.014501)
%     -> Outside/A (9.346490)
%     -> Toilet/A (16.404345)
%     -> Kitchen/A (89.883656)
%     -> KitchStor/A (122.351305)
%   Best match for SleepDoor/B: KitchHeat/A (0.289469)
%
%   Compute divergence scores for Sleep/B.
%     -> SleepDoor/A (0.695067)
%     -> BathroomDoor/A (0.932529)
%     -> KitchStor/A (2.636653)
%     -> Outside/A (4.519484)
%     -> Toilet/A (7.813519)
%     -> Kitchen/A (10.052727)
%     -> KitchHeat/A (10.692181)
%   Best match for Sleep/B: SleepDoor/A (0.695067)
%
%   Compute divergence scores for Bathroom/B.
%     -> SleepDoor/A (2.657258)
%     -> BathroomDoor/A (2.746026)
%     -> Kitchen/A (3.146785)
%     -> KitchStor/A (5.250662)
%     -> Outside/A (8.272006)
%     -> Toilet/A (9.846257)
%     -> KitchHeat/A (23.714785)
%   Best match for Bathroom/B: SleepDoor/A (2.657258)
%                                                                         %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
